package tum0r.webengine.core

import tum0r.webengine.config.ApplicationConfig
import tum0r.webengine.config.BaseConfig
import tum0r.webengine.config.SSLConfig
import tum0r.webengine.enums.EConfigType
import tum0r.webengine.extension.errorLog
import tum0r.webengine.extension.getAllNetCards
import tum0r.webengine.extension.infoLog
import tum0r.webengine.extension.isExistsFile
import tum0r.webengine.models.utils.netcard.NetCard
import java.io.FileInputStream
import java.net.InetAddress
import java.net.ServerSocket
import java.security.KeyStore
import java.security.SecureRandom
import java.security.cert.X509Certificate
import javax.net.ssl.*

/**
 * 说明: 服务器类
 *
 * 创建者: tum0r
 *
 * 时间: 2021/8/21 13:26
 */
class Server : Runnable {
    init {
        BaseConfig.setState(EConfigType.SERVER_IS_OPEN, true)
    }

    companion object {
        /**
         * 服务器所用的协议
         */
        val protocol = if (BaseConfig.isState(EConfigType.OPEN_HTTPS)) "https" else "http"
    }

    /**
     * 服务器Socket
     */
    private var serverSocket: ServerSocket? = null

    /**
     * 服务器IP地址
     */
    private val serverAddress = ArrayList<String>()

    /**
     * 添加服务器IP地址
     */
    private fun addIP(ips: ArrayList<String>, ip: String) {
        if (!ips.contains(ip)) ips.add(ip)
    }

    /**
     * 服务器启动成功后执行
     */
    private fun startSuccess() {
        val ips = ArrayList<String>()
        // 获取本机回环地址
        val address = InetAddress.getLocalHost()
        addIP(ips, address.hostAddress)
        addIP(ips, address.hostName)
        // 获取本机网卡地址
        val netCards = ArrayList<NetCard>()
        netCards.getAllNetCards()
        for (netCard in netCards)
            if (netCard.isUp() && !netCard.isLoopBack() and !netCard.isPointToPoint() && !netCard.isVirtual() && (netCard.name.startsWith("eth") || netCard.name.startsWith("en")))
                for (ip in netCard.ips) addIP(ips, ip.hostAddress)
        for (ip in ips) {
            val addressString = "$protocol://$ip:${ApplicationConfig.SERVER_PORT}/"
            serverAddress.add(addressString)
            "服务器启动成功 $addressString".infoLog()
        }
    }

    /**
     * 获取SSLServerSocket
     */
    private fun getSSLServerSocket(): SSLServerSocket {
        if (SSLConfig.KEY_STORE_FILE == null || !SSLConfig.KEY_STORE_FILE!!.isExistsFile(true)) "开启HTTPS必须先设置KeyStore文件".errorLog(true)
        // KeyStore
        val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
        var fileInputStream = FileInputStream(SSLConfig.KEY_STORE_FILE!!)
        keyStore.load(fileInputStream, SSLConfig.KEY_STORE_PASSWORD)
        fileInputStream.close()
        val keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
        keyManagerFactory.init(keyStore, SSLConfig.KEY_STORE_PASSWORD)

        // TrustKeyStore
        var trustManagerFactory: TrustManagerFactory? = null
        if (SSLConfig.TRUST_KEY_STORE_FILE != null && SSLConfig.TRUST_KEY_STORE_FILE!!.isExistsFile(true)) {
            val trustKeyStore = KeyStore.getInstance(KeyStore.getDefaultType())
            fileInputStream = FileInputStream(SSLConfig.TRUST_KEY_STORE_FILE!!)
            trustKeyStore.load(fileInputStream, SSLConfig.TRUST_KEY_STORE_PASSWORD)
            fileInputStream.close()
            trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())
            trustManagerFactory.init(keyStore)
        }

        // 获取信任库
        val trustManagers = if (trustManagerFactory == null) trustManagerFactory?.trustManagers
        else {
            arrayOf<TrustManager>(object : X509TrustManager {
                override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}

                override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}

                override fun getAcceptedIssuers(): Array<X509Certificate>? = null
            })
        }

        // 获取SSLServerSocket
        val sslContext = SSLContext.getInstance(SSLConfig.SECURITY_TYPE.type)
        sslContext.init(keyManagerFactory.keyManagers, trustManagers, SecureRandom())
        return sslContext.serverSocketFactory.createServerSocket(ApplicationConfig.SERVER_PORT) as SSLServerSocket
    }

    /**
     * 获取ServerSocket或SSLServerSocket
     */
    private fun getServerSocket(): ServerSocket {
        return if (!BaseConfig.isState(EConfigType.OPEN_HTTPS))
            ServerSocket(ApplicationConfig.SERVER_PORT)
        else
            getSSLServerSocket()
    }

    /**
     * 启动服务器
     */
    override fun run() {
        try {
            serverSocket = getServerSocket()
            startSuccess()
            while (!serverSocket!!.isClosed) {
                val socket = serverSocket!!.accept()
                // 如果IP被禁止就直接关闭连接
                val socketIP = socket.inetAddress.hostAddress
                var flag = false
                for (IP in ApplicationConfig.BAN_IP) {
                    if (socketIP.startsWith(IP)) {
                        flag = true
                        break
                    }
                }
                if (flag) {
                    socket.close()
                    continue
                }
                ApplicationConfig.THREAD_POOL.execute(RequestHandler(socket))
            }
        } catch (e: Exception) {
            if (e.message != "Socket closed") {
                close()
                "服务器启动失败".errorLog()
                e.errorLog(true)
            }
        }
    }

    /**
     * 关闭服务器
     */
    fun close() {
        serverSocket?.close()
        ApplicationConfig.THREAD_POOL.shutdown()
        "服务器已关闭".infoLog()
    }
}